﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DevExpress.Spreadsheet;
using DevExpress.XtraBars.Docking2010.Views.WindowsUI;
using DevExpress.XtraSpreadsheet;
using DevExpress.XtraSpreadsheet.Menu;
using EduFormManager.Models;
using EduFormManager.Models.Repo;
using EduFormManager.Properties;
using EduFormManager.Utilities;

namespace EduFormManager.Forms.UserControls
{
    public partial class XtraDictionaryTemplateControl : XtraBaseControl, ISupportDocumentActions
    {
        public XtraDictionaryTemplateControl(WindowsUIView view, Repository repo)
            : base(view, repo)
        {
            InitializeComponent();
        }

        public override List<templated_form_data> TemplatedFormDataDataSource
        {
            set
            {
                templatedFormDataBindingSource.DataSource = value;
                UpdateData();
            }
        }

        public void New()
        {
            New(null);
        }
        protected override void New(Document doc)
        {
            using (var openFileDialog = new OpenFileDialog())
            {
                openFileDialog.ShowDialog(this);
                if (string.IsNullOrEmpty(openFileDialog.FileName))
                {
                    return;
                }
                var template = Repo.Db.templated_form_data.Create();
                spreadsheetTemplate.LoadDocument(openFileDialog.FileName);
                spreadsheetTemplate.Document.History.IsEnabled = true;
                using (var ms = new MemoryStream())
                {
                    spreadsheetTemplate.SaveDocument(ms, DocumentFormat.OpenXml);
                    var data = ms.ToArray();
                    template.file_data = data;
                }
                var form = (form)comboBoxRemainingTemplatedForm.SelectedItem;
                template.form = form;

                var encoding = Encoding.UTF8; //Encoding.GetEncoding(checkData.CodePage);
                var textContent = encoding.GetString(form.check_file_data ?? new byte[0]);
                this.formulaEditControl1.Text = textContent;

                formBindingSource.Remove(form);
                templatedFormDataBindingSource.Add(template);
                var i = templatedFormDataBindingSource.IndexOf(template);
                templatedFormDataBindingSource.Position = i;
            }
        }
        public bool CanNew()
        {
            return CanNew(null);
        }
        protected override bool CanNew(Document doc)
        {
            return true;
        }
        public void Save()
        {
            Save(null);
        }
        protected override async void Save(Document doc)
        {
            templatedFormDataBindingSource.EndEdit();
            ProgressDialog.ShowTop(this.ParentForm, description: "Сохраняю");

            var template = (templated_form_data)templatedFormDataBindingSource.Current;
            var formId = template.form.form_id;
            if ((await Repo.Db.templated_form_data.CountAsync(t => t.form_id == formId)) == 0)
                Repo.Db.templated_form_data.Add(template);

            //var form = (form) formBindingSource.Current;
            var form = template.form;
            var encoding = Encoding.UTF8;

            form.check_file_data = encoding.GetBytes(this.formulaEditControl1.Text);;
            form.check_file_md5 = FileUtility.GetCRC32AsHexString(form.check_file_data);

            await Repo.Db.SaveChangesAsync();

            //formBindingSource.Remove(form);
            //formBindingSource.Position = 0;

            ProgressDialog.HideTop();   
        }

        public bool CanSave()
        {
            return CanSave(null);
        }
        protected override bool CanSave(Document doc)
        {
            return templatedFormDataBindingSource.Current != null && spreadsheetTemplate.Document != null;
        }
        public void Remove()
        {
            Remove(null);
        }
        protected override async void Remove(Document doc)
        {
            var template = (templated_form_data) templatedFormDataBindingSource.Current;
            Repo.Db.templated_form_data.Remove(template);
            templatedFormDataBindingSource.Remove(template);
            templatedFormDataBindingSource.EndEdit();
            await Repo.Db.SaveChangesAsync();
            UpdateData();
        }
        public bool CanRemove()
        {
            return CanRemove(null);
        }
        protected override bool CanRemove(Document doc)
        {
            return templatedFormDataBindingSource.Current != null;
        }

        protected async void UpdateData()
        {
            templatedFormDataBindingSource.DataSource = await Repo.GetTemplates();
            formBindingSource.DataSource = await Repo.GetFormsWithoutTemplates();
        }

        async private void listBoxTemplatedForm_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.formulaEditControl1.Text = string.Empty;
            var template = (templated_form_data) templatedFormDataBindingSource.Current;
            if (template == null)
            {
                return;
            }
            var excelData = template.file_data;
            if (excelData == null)
            {
                return;
            }
            using (var ms = new MemoryStream(excelData))
            {
                var format = DocumentFormat.OpenXml;
                spreadsheetTemplate.LoadDocument(ms, format);
                spreadsheetTemplate.Document.History.IsEnabled = true;
            }
            var form = template.form;
            var checkData = form.check_file_data;
            this.layoutControl1.Enabled = false;
            if (checkData != null)
            {
                var textContent = await Task.Run(() =>
                {
                    var crc = FileUtility.GetCRC32AsHexString(checkData);
                    var encoding = Encoding.UTF8;
                    return crc.Equals(form.check_file_md5) ? encoding.GetString(checkData) : null;
                });
                if (textContent != null)
                {
                    this.formulaEditControl1.Text = textContent;
                }
                else
                {
                    this.formulaEditControl1.Text = string.Empty;
                    this.ShowFlyoutMessageBox("Ошибка загрузки формул", "Ошибка целостности данных", FlyoutCommand.OK);
                }
            }
            this.layoutControl1.Enabled = true;
        }

        public void OnQueryDocumentActions(IDocumentActionsArgs args)
        {
            args.DocumentActions.Add(new DocumentAction(New) { Caption = "Открыть файл", Image = Resources.glyphicons_144_folder_open });
            args.DocumentActions.Add(new DocumentAction(CanSave, Save) { Caption = "Сохранить", Image = Resources.glyphicons_206_ok_2 });
            args.DocumentActions.Add(new DocumentAction(CanRemove, Remove) { Caption = "Удалить", Image = Resources.glyphicons_207_remove_2 });
        }

        private void comboBoxRemainingTemplatedForm_KeyPress(object sender, KeyPressEventArgs e)
        {
            e.Handled = true;
        }

        private void comboBoxRemainingTemplatedForm_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.listBoxTemplatedForm.ClearSelected();
            this.spreadsheetTemplate.CreateNewDocument();
            this.formulaEditControl1.Text = string.Empty;
        }

        private void spreadsheetTemplate_PopupMenuShowing(object sender, PopupMenuShowingEventArgs e)
        {
            if (e.MenuType == SpreadsheetMenuType.Cell)
            {
                e.Menu.Items.Clear();
                var ranges = this.spreadsheetTemplate.GetSelectedRanges();
                var itemAddLeft         = new SpreadsheetMenuItem("Добавить cлева", (o, args) => this.formulaEditControl1.AddToLeftPart(ranges));
                var itemReplaceLeft     = new SpreadsheetMenuItem("Заменить слева", (o, args) => this.formulaEditControl1.ReplaceLeftPart(ranges));
                var itemAddRight        = new SpreadsheetMenuItem("Добавить справа", (o, args) => this.formulaEditControl1.AddToRightPart(ranges));
                var itemReplaceRight    = new SpreadsheetMenuItem("Заменить справа", (o, args) => this.formulaEditControl1.ReplaceRightPart(ranges));

                itemAddLeft.BeginGroup = true;
                e.Menu.Items.Add(itemAddLeft);
                e.Menu.Items.Add(itemReplaceLeft);
                itemAddRight.BeginGroup = true;
                e.Menu.Items.Add(itemAddRight);
                e.Menu.Items.Add(itemReplaceRight);
            }
        }

        private void listBoxTemplatedForm_Format(object sender, ListControlConvertEventArgs e)
        {
            e.Value = ((templated_form_data) e.ListItem).form.name;
        }
    }
}